home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-02-26 | 6.1 KB | 189 lines | [TEXT/CCL2] |
- ;;; faultrease:rulers.lisp
- ;;; methods to draw rulers in a window
- ;;; this file is part of the faultrease system
- ;;; by: gregory c. wilcox
- ;;; arthur d. little, inc.
- ;;; october, 1992
-
- ;;; to turn rulers on: (setf (slot-value <window> 'rulers) <zoom>)
- ;;; to turn rulers off: (setf (slot-value <window> 'rulers) nil)
- ;;; where <window> is a scrolling-window-with-rulers
- ;;; and <zoom> is the zoom ratio
- ;;;
- ;;; when rulers are on, the current mouse location will be tracked
- ;;; in the rulers, using a gray pattern
- ;;;
- ;;; to set ruler units: (setq *ruler-units* <unit>)
- ;;; where <unit> is one of (inch centimeter point pixel)
-
- (defvar *ruler-units* 'inch "Units used in rulers.")
-
- (defvar *ruler-offset* (make-point 16 16) "View offset when rulers are in use.")
-
- (defvar *mouse* 0 "Current location of the mouse.")
-
- (defclass scrolling-window-with-rulers (ccl::scrolling-window)
- ((rulers :initarg :rulers :initform nil)
- ))
-
- (defmacro axis-point (axis x y)
- "Make a point along a given axis."
- `(ecase ,axis
- (x (make-point ,x ,y))
- (y (make-point ,y ,x))
- ))
-
- (defmacro with-xor-gray-pen (&body body)
- (let ((state (gensym)))
- `(rlet ((,state :PenState))
- (require-trap #_GetPenState ,state)
- (require-trap #_PenPat *gray-pattern*)
- ;; have to use :patxor (not :srcxor) so it works on monochrome machines
- (require-trap #_PenMode ,(position :patxor *pen-modes*))
- (unwind-protect (progn ,@body)
- (require-trap #_SetPenState ,state)
- ))))
-
- (defun tic-size (j)
- (let* ((i (mod j 8))
- (k (logand i (- 8 i))))
- (if (zerop k) 8 k)
- ))
-
- (defun draw-ruler (axis max zoom ppu)
- "Draw a ruler along the X or Y axis."
- (let ((width 16)
- (scale (if (eq *ruler-units* 'point) 100 1)))
- (frame-rect (axis-point axis width 0)
- (axis-point axis max width))
- (with-font-spec '("geneva" 9 :plain)
- (do* ((i 0 (1+ i))
- (x width (+ width (round (* i (/ 1 8) ppu)))))
- ((> x max))
- (when (zerop (mod i 8))
- (ecase axis
- (x (move-to (+ x 2) 10))
- (y (move-to 2 (- x 2))))
- (with-pstrs ((string (prin1-to-string (* zoom scale (/ i 8)))))
- (#_DrawString string)))
- (let ((tic-length (ash (tic-size i) 1)))
- (move-to (axis-point axis x (- width 1)))
- (line-to (axis-point axis x (- width tic-length)))
- )))))
-
- (defun pixels-per-unit (axis)
- (ecase *ruler-units*
- (inch (ecase axis
- (x *pixels-per-inch-x*)
- (y *pixels-per-inch-y*)))
- ;; an educated guess. sue me
- (centimeter 28)
- ((point pixel) 100)
- ))
-
- (defmethod draw-rulers ((window scrolling-window-with-rulers))
- "Draw rulers at the axes."
- ;; rulers object variable used to hold the zoom ratio
- (let* ((zoom (slot-value window 'rulers))
- (size (view-size window))
- (x (point-h size))
- (y (point-v size))
- )
- (draw-ruler 'x x zoom (pixels-per-unit 'x))
- (draw-ruler 'y y zoom (pixels-per-unit 'y))
- ))
-
- (defmethod add-rulers ((window scrolling-window-with-rulers))
- (let* ((scroller (my-scroller window))
- (new-size (subtract-points (view-size scroller)
- *ruler-offset*)))
- (set-view-size scroller new-size)
- (set-view-position scroller *ruler-offset*)
- ))
-
- (defmethod remove-rulers ((window scrolling-window-with-rulers))
- (let* ((scroller (my-scroller window))
- (new-size (add-points (view-size scroller) *ruler-offset*)))
- (set-view-size scroller new-size)
- (set-view-position scroller (make-point 0 0))
- ;; this could be done more efficiently
- ;; using inval-rect on the ruler regions
- (redraw window)
- ))
-
- (defmethod scroller-size ((window scrolling-window-with-rulers))
- ;; allow for scroll bars
- (let ((new-size (subtract-points (view-size window) #@(15 15))))
- ;; allow for rulers, if present
- (if (slot-value window 'rulers)
- (subtract-points new-size *ruler-offset*)
- new-size
- )))
-
- (defmethod my-scroller ((window scrolling-window-with-rulers))
- (ccl::my-scroller window))
-
- ;;; next three functions were
- ;;; adapted from functions in ccl;examples;scrolling-windows.lisp
- ;;; all that's missing is a definition of initialize-instance,
- ;;; after which scrolling-window-with-rulers could inherit directly from window
- ;;; and not need scrolling-windows
-
- (defmethod set-view-size ((window scrolling-window-with-rulers) h &optional v)
- "Modify (set-view-size scrolling-window) for rulers."
- (declare (ignore h v))
- (without-interrupts
- (call-next-method)
- (set-view-size (my-scroller window) (scroller-size window))
- ))
-
- (defmethod view-draw-contents ((window scrolling-window-with-rulers))
- (call-next-method)
- (when (slot-value window 'rulers)
- (unless (hardcopy-p)
- (draw-rulers window)
- )))
-
- (defmethod window-zoom-event-handler ((window scrolling-window-with-rulers) message)
- (declare (ignore message))
- (without-interrupts
- (call-next-method)
- (set-view-size (my-scroller window) (scroller-size window))
- ))
-
- (defmacro mark-rulers (location)
- "Mark the current location on the rulers."
- ;; speed-hacked and macro-ized since it's in the main event loop
- `(let ((h (point-h ,location))
- (v (point-v ,location)))
- (declare (optimize (speed 3) (safety 0)))
- (require-trap #_MoveTo 0 v)
- (require-trap #_LineTo 16 v)
- (require-trap #_MoveTo h 0)
- (require-trap #_LineTo h 16)
- ))
-
- (defmethod show-location ((window scrolling-window-with-rulers))
- "Track mouse motion in the rulers."
- (let ((mouse (view-mouse-position window)))
- (when (neq mouse *mouse*)
- (with-focused-view window
- (with-xor-gray-pen
- ;; fencepost fixup
- (unless (zerop *mouse*) (mark-rulers *mouse*))
- (setq *mouse* mouse)
- (mark-rulers *mouse*)
- )))))
-
- (defmethod window-event ((window scrolling-window-with-rulers))
- "If rulers are on, show current mouse location."
- (call-next-method)
- (when (and
- (slot-value window 'rulers)
- ;; have to check this in case window event = close
- (wptr window))
- (show-location window)
- ))
-
- ;;; end of file
-